#include "asan_interfaces_internal.h"
#include "asan_internal_defs.h"
#include "asan_internal.h"
#include "asan_alloctor.h"
#include "sanitizer_libc.h"
#include "asan_report.h"

namespace __sanitizer {

static const u64 kMagic1 = kAsanStackAfterReturnMagic;
static const u64 kMagic2 = (kMagic1 << 8) | kMagic1;
static const u64 kMagic4 = (kMagic2 << 16) | kMagic2;
static const u64 kMagic8 = (kMagic4 << 32) | kMagic4;

static const u64 kAllocaRedzoneSize = 32UL;
static const u64 kAllocaRedzoneMask = 31UL;

extern "C" {

SANITIZER_INTERFACE_ATTRIBUTE void __asan_alloca_poison(uptr addr, uptr size) {
  uptr LeftRedzoneAddr = addr - kAllocaRedzoneSize;
  allocatorPtr->shadow->PoisonMem((void*)LeftRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaLeftMagic);
  allocatorPtr->shadow->UnpoisonMem((void*)addr, size);
  // add some right redzone
  uptr RightRedzoneAddr = addr + size;
  allocatorPtr->shadow->PoisonMem((void*)RightRedzoneAddr, kAllocaRedzoneSize, kAsanAllocaRightMagic);
}


SANITIZER_INTERFACE_ATTRIBUTE
void __asan_allocas_unpoison(uptr top, uptr bottom) {
  if ((!top) || (top > bottom)) return;
  internal_memset((void*)MEM_TO_SHADOW(top), 0, (bottom - top) / ASAN_SHADOW_GRANULARITY);
}

SANITIZER_INTERFACE_ATTRIBUTE
void __asan_check_stack(uptr top, uptr bottom) {
  if ((!top) || (top > bottom)) return;
  CheckAndReport((void*)top, bottom - top, false);
}

SANITIZER_INTERFACE_ATTRIBUTE
void __asan_check_stack2(uptr top, uptr size) {
  CheckAndReport((void*)top, size, false);
}

}

} // namespace __sanitizer